package com.glela.task;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;

import javax.annotation.Resource;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import com.glela.api.pay.alipay.component.Alipay;
import com.glela.api.pay.wechat.component.WeChat;
import com.glela.common.util.ExcelUtil;
import com.glela.common.util.ListUtils;
import com.glela.email.service.EmailService;
import com.glela.model.ValidationAfterSale;
import com.glela.model.ValidationCannelOrder;
import com.glela.model.ValidationOrder;
import com.glela.model.ValidationUser;
import com.glela.order.mapper.AfterSalesMapper;
import com.glela.order.mapper.OrderObjectMapper;
import com.glela.order.mapper.OrderPayMapper;
import com.glela.order.model.AfterSales;
import com.glela.order.model.OrderObject;
import com.glela.order.service.AfterSalesService;
import com.glela.order.service.OrderPayService;
import com.glela.order.service.OrderService;
import com.glela.platform.mapper.UserMoneyMapper;
import com.glela.platform.mapper.UserMoneySnapshotMapper;
import com.glela.platform.model.BaseRestrictions;
import com.glela.platform.service.BaseRestrictionsService;
import com.glela.statistics.mapper.OrderStatisticsMapper;
import com.glela.talent.util.MyDateUtil;

/**
 * 数据校验的定时任务
 * 
 * @author gwq
 */
public class ValidationDataTask {
	
	private static final Logger logger = LoggerFactory.getLogger(ValidationDataTask.class);
	private static SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月dd日hh时mm分ss秒");
	private static MyDateUtil util = MyDateUtil.INSTANCE;
	@Autowired
	private OrderObjectMapper orderObjectMapper;
	@Resource(name = "orderService2")
	private OrderService orderService2;
	@Autowired
	private ThreadPoolTaskExecutor ThreadPool;
	@Autowired
	private AfterSalesService afterSalesService;
	@Autowired
	private List<WeChat> weChatList;
	@Autowired
	private Alipay alipay;
	@Autowired
	private OrderPayService orderPayService;
	@Autowired
	private OrderPayMapper orderPayMapper;
	@Autowired
	private AfterSalesMapper afterSalesMapper;
	@Autowired
	private OrderStatisticsMapper orderStatisticsMapper;
	@Autowired
	private UserMoneyMapper userMoneyMapper;
	@Autowired
	private UserMoneySnapshotMapper userMoneySnapshotMapper;
	@Autowired
	private BaseRestrictionsService baseRestrictionsService;
	@Autowired
	private EmailService emailService;
	
	/**
	 * <dl>
	 * <dt>发送数据验证的邮件</dt>
	 * </dl>
	 * 凌晨8点执行
	 * @author gaoweiqi
	 * @date 2018年01月26日 16:44:05
	 */
	public void SendErrorDataByEmail() {
		try {
			BaseRestrictions AbnormalOrdersSendUsers = baseRestrictionsService.getBaseRestrictionsForCache("AbnormalOrdersSendUsers");// 发送给
			BaseRestrictions AbnormalOrdersCCUsers = baseRestrictionsService.getBaseRestrictionsForCache("AbnormalOrdersCCUsers");// 抄送给
			if (AbnormalOrdersSendUsers != null && AbnormalOrdersSendUsers.getStatus() == 1 && AbnormalOrdersCCUsers != null && AbnormalOrdersCCUsers.getStatus() == 1) {
				File path = new File(File.separator + "异常数据");
				Map<String, String> Map = new HashMap<String, String>();
				Map<String, File> FileList = new HashMap<String, File>();
				Map.put("userName", "高玮琪");
				for (File file : path.listFiles()) {
					if (file.getName().endsWith(".xlsx") && StringUtils.contains(file.getName(), "异常")) {// 异常excel
						FileList.put(file.getName(), file);
					}
				}
				emailService.sendBatchEmail(AbnormalOrdersSendUsers.getName(), AbnormalOrdersCCUsers.getName(), "异常订单", Map, null, FileList, "validationHasError.ftl");
				//没有问题 邮件已发送 删除文件
				FileUtils.deleteDirectory(path);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	/**
	 * <dl>
	 * <dt>校验昨天的订单是否有问题</dt>
	 * </dl>
	 * 凌晨3点执行
	 * @author gaoweiqi
	 * @date 2018年01月26日 16:44:05
	 */
	public void validtionData() {
		/* 仅验证更新时间在昨天一整天的订单 用户 流水数据 */
		String beginTime = util.getOldDays(1);
		String snapTime = util.getOldDays(-1);
		String endTime = util.getYesterday(new Date());
		try {
			validtionOrder(beginTime, endTime);
            //validtionUser();
			validtionjournal(beginTime, snapTime, endTime);
		} catch (Exception e) {
			logger.info(e.getMessage());
		}
	}
	
	protected void validtionOrder(String beginTime, String endTime) throws Exception {
		Map<String, List<Map<String, Object>>> results = new HashMap<String, List<Map<String, Object>>>();
		Map<String, String[]> names = new HashMap<>();
		Map<String, String> keyword = new HashMap<>();
		String file_name = File.separator + "异常数据" + File.separator + "(" + df.format(new Date()) + ")订单异常.xlsx";
		int[] statusArray = { 2, 3, 4, 6, 7 };// 支付成功的订单
		// 1.验证当天的订单情况 去易宝查一下支付状态
		long times = System.currentTimeMillis();
		List<OrderObject> listOBJ = orderObjectMapper.selectOrderObjectByStatusAndUpdateTime(statusArray, beginTime, endTime);
		logger.info("查找订单数据 " + beginTime + "--" + "endTime 耗时(秒):" + ((System.currentTimeMillis() - times) / 1000.0) + "  找到行数:" + listOBJ.size());
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		int index = 0;
		List<Future<List<Map<String, Object>>>> FutureList = new ArrayList<>();
		List<OrderObject> listOBJTemp = listOBJ.size() > 100 ? listOBJ.subList(0, index = index + 100) : listOBJ;
		times = System.currentTimeMillis();
		while (ListUtils.isNotEmpty(listOBJTemp)) {
			ValidationOrder orderTest = new ValidationOrder(listOBJTemp, orderService2);
			Future<List<Map<String, Object>>> future = ThreadPool.submit(orderTest);
			FutureList.add(future);
			listOBJTemp = listOBJ.subList(index, index = (index + 100) > listOBJ.size() ? (listOBJ.size()) : (index + 100));
		}
		while (true) {
			boolean isAllDone = true;
			for (Future<List<Map<String, Object>>> future : FutureList) {
				isAllDone &= (future.isDone() || future.isCancelled());
			}
			if (isAllDone) {
				break;
			}
		}
		for (Future<List<Map<String, Object>>> ss : FutureList) {
			try {
				result.addAll(ss.get());
			} catch (Exception e) {
				System.out.println("Exception：" + e.getMessage());
			}
		}
		logger.info("耗时 :" + ((System.currentTimeMillis() - times) / 1000.0));
		results.put("1", result);// 异常订单
		names.put("1", new String[] { "父订单号", "异常原因" });// 列名
		keyword.put("1", "异常订单");// sheet name
		// 2. 查找所有的状态是1或者5的单子
		index = 0;
		result = new ArrayList<Map<String, Object>>();
		times = System.currentTimeMillis();
		List<OrderObject> payObj = orderObjectMapper.selectOrderObjectByStatusAndUpdateTime(new int[] { 1, 5 }, beginTime, endTime);
		logger.info("查找未支付订单数据 " + beginTime + "--" + "endTime 耗时(秒):" + ((System.currentTimeMillis() - times) / 1000.0) + "  找到行数:" + payObj.size());
		FutureList = new ArrayList<>();
		listOBJTemp = payObj.size() > 100 ? payObj.subList(0, index = index + 100) : payObj;
		times = System.currentTimeMillis();
		while (ListUtils.isNotEmpty(listOBJTemp)) {
			ValidationCannelOrder orderTest = new ValidationCannelOrder(listOBJTemp, orderPayMapper, orderPayService, weChatList, orderService2, alipay);
			Future<List<Map<String, Object>>> future = ThreadPool.submit(orderTest);
			FutureList.add(future);
			listOBJTemp = payObj.subList(index, index = (index + 100) > payObj.size() ? (payObj.size()) : (index + 100));
		}
		while (true) {
			boolean isAllDone = true;
			for (Future<List<Map<String, Object>>> future : FutureList) {
				isAllDone &= (future.isDone() || future.isCancelled());
			}
			if (isAllDone) {
				break;
			}
		}
		for (Future<List<Map<String, Object>>> ss : FutureList) {
			result.addAll(ss.get());
		}
		logger.info("耗时 :" + ((System.currentTimeMillis() - times) / 1000.0));
		results.put("2", result);// 异常订单
		names.put("2", new String[] { "父订单号", "异常原因" });// 列名
		keyword.put("2", "支付异常订单");// sheet name
		// 3.验证售后单 查找当天更新的售后单
		index = 0;
		result = new ArrayList<Map<String, Object>>();
		times = System.currentTimeMillis();
		List<AfterSales> AfterSalesListTemp = new ArrayList<>();
		List<AfterSales> AfterSalesList = afterSalesMapper.selectAfterSalesByUpdateTime(beginTime, endTime);
		logger.info("查找售后单数据 " + beginTime + "--" + "endTime 耗时(秒):" + ((System.currentTimeMillis() - times) / 1000.0) + "  找到行数:" + listOBJ.size());
		AfterSalesListTemp = AfterSalesList.size() > 100 ? AfterSalesList.subList(0, index = index + 100) : AfterSalesList;
		FutureList = new ArrayList<>();
		times = System.currentTimeMillis();
		while (ListUtils.isNotEmpty(AfterSalesListTemp)) {
			ValidationAfterSale orderTest = new ValidationAfterSale(AfterSalesListTemp, afterSalesService);
			Future<List<Map<String, Object>>> future = ThreadPool.submit(orderTest);
			FutureList.add(future);
			AfterSalesListTemp = AfterSalesList.subList(index, index = (index + 100) > AfterSalesList.size() ? (AfterSalesList.size()) : (index + 100));
		}
		while (true) {
			boolean isAllDone = true;
			for (Future<List<Map<String, Object>>> future : FutureList) {
				isAllDone &= (future.isDone() || future.isCancelled());
			}
			if (isAllDone) {
				break;
			}
		}
		for (Future<List<Map<String, Object>>> ss : FutureList) {
			result.addAll(ss.get());
		}
		logger.info("耗时 :" + ((System.currentTimeMillis() - times) / 1000.0));
		results.put("3", result);// 异常订单
		names.put("3", new String[] { "售后单号", "异常原因" });// 列名
		keyword.put("3", "异常售后单");// sheet name
		ExcelUtil.writeExecl(file_name, results, names, keyword);
	}
	
	/** 验证用户信息 */
	protected void validtionUser() throws Exception {
		Map<String, List<Map<String, Object>>> results = new HashMap<String, List<Map<String, Object>>>();
		Map<String, String[]> names = new HashMap<>();
		Map<String, String> keyword = new HashMap<>();
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		String file_name = File.separator + "异常数据" + File.separator + "(" + df.format(new Date()) + ")用户异常.xlsx";
		// 8 验证用户身份信息异常的用户
		List<Future<List<Map<String, Object>>>> FutureList = new ArrayList<>();
		ValidationUser ValidationUser = new ValidationUser(orderStatisticsMapper);
		FutureList.add(ThreadPool.submit(ValidationUser));
		while (true) {
			boolean isAllDone = true;
			for (Future<List<Map<String, Object>>> future : FutureList) {
				isAllDone &= (future.isDone() || future.isCancelled());
			}
			if (isAllDone) {
				break;
			}
		}
		for (Future<List<Map<String, Object>>> future : FutureList) {
			result.addAll(future.get());
		}
		results.put("1", result);// 异常订单
		names.put("1", new String[] { "用户ID", "登录名", "登录人身份", "异常原因", "推荐人ID", "推荐人登录账号", "推荐人身份", "达人导师ID", "达人导师登录账号", "达人导师身份" });// 列名
		keyword.put("1", "用户身份异常");// sheet name
		ExcelUtil.writeExecl(file_name, results, names, keyword);
	}
	
	/** 验证用户流水 */
	protected void validtionjournal(String beginTime, String snapTime, String endTime) throws Exception {
		Map<String, List<Map<String, Object>>> results = new HashMap<String, List<Map<String, Object>>>();
		Map<String, String[]> names = new HashMap<>();
		Map<String, String> keyword = new HashMap<>();
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		String file_name = File.separator + "异常数据" + File.separator + "(" + df.format(new Date()) + ")流水异常.xlsx";
		// 6.验证账户的余额妆币流水变化过程
		// 验证账户余额变化过程异常(某一时刻 期初减期末成为负数)
		List<Map<Object, Object>> MoneyProcessMap = orderStatisticsMapper.validationUserMoneyProcess();
		List<Map<Object, Object>> PointProcessMap = orderStatisticsMapper.validationUserPointProcess();
		long userID = 0L;// 当前正在计算中的用户ID
		long ErrorUserID = 0L;// 当前流水发生错误的用户ID
		int UserMoney = 0;
		for (Map<Object, Object> temp : MoneyProcessMap) {
			long TempUserID = temp.get("user_id") == null ? 0 : Long.parseLong(temp.get("user_id").toString());
			int TempMoney = temp.get("money") == null ? 0 : Integer.parseInt(temp.get("money").toString());
			String Flag = temp.get("type") == null ? "" : temp.get("type").toString();
			if (TempUserID == 0L || TempUserID == 0 || !"+-".contains(Flag)) {
				continue;
			}
			if (ErrorUserID == TempUserID) {// 当前的用户上一条流水已经发生错误了
				continue;
			}
			
			if (TempUserID != userID) {// 开始判断下一个用户的流水 重置数据
				userID = TempUserID;
				UserMoney = 0;
			}
			// 但比计算逻辑
			if ("+".equals(Flag)) {
				UserMoney += TempMoney;
			} else {
				UserMoney -= TempMoney;
			}
			// 当前的流水异常 异常流水从2018年初开始算
			if (UserMoney < 0 && StringUtils.compare(temp.get("create_time").toString(), "2018-01-01 00:00:00") > 0) {
				ErrorUserID = TempUserID;
				Map<String, Object> maps = new HashMap<String, Object>();
				maps.put("1", String.valueOf(ErrorUserID));
				maps.put("2", "用户余额流水异常 用户ID :" + ErrorUserID + " 异常流水ID: " + temp.get("id"));
				result.add(maps);
			}
		}
		results.put("1", result);// 异常订单
		names.put("1", new String[] { "用户ID", "异常原因" });// 列名
		keyword.put("1", "用户余额流水异常");// sheet name
		
		result = new ArrayList<Map<String, Object>>();
		userID = 0L;
		ErrorUserID = 0L;
		UserMoney = 0;
		for (Map<Object, Object> temp : PointProcessMap) {
			long TempUserID = temp.get("user_id") == null ? 0 : Long.parseLong(temp.get("user_id").toString());
			int TempMoney = temp.get("amount") == null ? 0 : Integer.parseInt(temp.get("amount").toString());
			if (TempUserID == 0L || TempUserID == 0) {
				continue;
			}
			if (ErrorUserID == TempUserID) {// 当前的用户上一条流水已经发生错误了
				continue;
			}
			
			if (TempUserID != userID) {// 开始判断下一个用户的流水 重置数据
				userID = TempUserID;
				UserMoney = 0;
			}
			// 但比计算逻辑
			UserMoney += TempMoney;
			// 当前的流水异常
			if (UserMoney < 0 && StringUtils.compare(temp.get("create_time").toString(), "2018-01-01 00:00:00") > 0) {
				ErrorUserID = TempUserID;
				Map<String, Object> maps = new HashMap<String, Object>();
				maps.put("1", String.valueOf(ErrorUserID));
				maps.put("2", "用户妆币流水异常 用户ID :" + ErrorUserID + " 异常流水ID: " + temp.get("id"));
				result.add(maps);
			}
		}
		results.put("2", result);// 异常订单
		names.put("2", new String[] { "用户ID", "异常原因" });// 列名
		keyword.put("2", "用户妆币流水异常");// sheet name
		// 2 验证账户金额和流水不一致的用户
		List<Map<String, Object>> listUserTh = userMoneyMapper.validationUserMoney();
		results.put("3", listUserTh);// 异常订单
		names.put("3", new String[] { "用户ID", "余户余额", "余额流水", "用户妆币", "妆币流水" });// 列名
		keyword.put("3", "账户金额和流水不一致的用户");// sheet name
		// 1 验证当天的快照是否有异常 保证当天的快照和账户余额流水能够核对的上
		List<Map<Object, Object>> vlidationSnapShotList = userMoneySnapshotMapper.ValidationSnapShot(beginTime, snapTime, endTime);
		result = new ArrayList<Map<String, Object>>();
		for (Map<Object, Object> maps : vlidationSnapShotList) {
			Map<String, Object> tempMap = new HashMap<String, Object>();
			tempMap.put("1", maps.get("user_id").toString());
			tempMap.put("2", "用户当日快照异常");
			result.add(tempMap);
		}
		results.put("4", result);// 异常订单
		names.put("4", new String[] { "用户ID", "异常原因" });// 列名
		keyword.put("4", "妆币快照异常");// sheet name
		ExcelUtil.writeExecl(file_name, results, names, keyword);
	}
}
